﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace Grizzy_X
{
    public class CLineLayer : CLayer
    {
        public List<CLine> Line_Set;
        public Bitmap lnlayer;

        public bool NewLineLayer(int id, string name, string path, string des)
        {
            try
            {
                ID = id;
                Name = name;
                Path = path;
                Layer_Type = LayerType.CLineLayer;
                bSelected = true;
                bVisible = true;
                Line_Set = new List<CLine>();
                Description = des;
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool AddLine(CLine NewLine)
        {
            try
            {
                Line_Set.Add(NewLine);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool DeleteLine()
        {
            try
            {
                for (int i = 0; i < Controller.Selected.Count(); i++)
                {
                    Line_Set.RemoveAt(Controller.Selected[i]);
                    Line_Set.Insert(Controller.Selected[i], new CLine());
                    Line_Set[Controller.Selected[i]].Lines = new List<List<PointF>>();
                }
                for (int i = 0; i < Line_Set.Count(); i++)
                {
                    if (Line_Set[i].Lines.Count() == 0)
                    {
                        Line_Set.RemoveAt(i);
                        i--;
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        public Point snapnode(PointF e)
        {
            Point cursorp = new Point(-1, -1);
            float trans;
            if (Controller.MyMap.Unit == "英寸")
                trans = (float)1 / 96;
            else
                trans = (float)2.54 / 96;
            float Buffer = 13* trans;
            for (int m = 0; m < Line_Set.Count(); m++)
            {
                    for (int i = 0; i < Line_Set[m].Lines.Count(); i++)
                    {
                        for (int j = 0; j < Line_Set[m].Lines[i].Count(); j++)
                        {
                            if (Math.Abs(Line_Set[m].Lines[i][j].X - e.X) < Buffer
                                && Math.Abs(Line_Set[m].Lines[i][j].Y - e.Y) < Buffer)
                            {
                                Point temp = Transformer.ToScreen(Line_Set[m].Lines[i][j]);
                                cursorp = new Point(temp.X + 195, temp.Y + 125);
                            }
                        }
                    }
            }
            return cursorp;
        }
        public Point snapedge(PointF e)
        {
            Point cursorp = new Point(-1, -1);
            float trans;
            if (Controller.MyMap.Unit == "英寸")
                trans = (float)1 / 96;
            else
                trans = (float)2.54 / 96;
            float Buffer = 13* trans;
            for (int m = 0; m < Line_Set.Count(); m++)
            {
                if (Line_Set[m].MinBR.Lx - Buffer < e.X &&
                    Line_Set[m].MinBR.Ly - Buffer < e.Y &&
                   Line_Set[m].MinBR.Rx + Buffer > e.X &&
                    Line_Set[m].MinBR.Ry + Buffer > e.Y)
                {
                    for (int i = 0; i < Line_Set[m].Lines.Count(); i++)
                    {
                        float PI = (float)Math.PI;
                        Buffer = Math.Max(((CLineLegend)Controller.MapLegends[Line_Set[m].LegendID]).line_weight * trans / 2, 13 * trans);
                        for (int j = 0; j + 1 < Line_Set[m].Lines[i].Count(); j++)
                        {
                            List<PointF> RecBuffer = new List<PointF>();
                            PointF P1 = Line_Set[m].Lines[i][j];
                            PointF P2 = Line_Set[m].Lines[i][j + 1];
                            float slope = (float)Math.Atan((P1.Y - P2.Y) / (P1.X - P2.X));
                            RecBuffer.Add(new PointF(P1.X + Buffer * (float)Math.Cos(slope - 0.75 * PI), P1.Y + Buffer * (float)Math.Sin(slope - 0.75 * PI)));
                            RecBuffer.Add(new PointF(P1.X + Buffer * (float)Math.Cos(slope + 0.75 * PI), P1.Y + Buffer * (float)Math.Sin(slope + 0.75 * PI)));
                            RecBuffer.Add(new PointF(P2.X + Buffer * (float)Math.Cos(slope + 0.25 * PI), P2.Y + Buffer * (float)Math.Sin(slope + 0.25 * PI)));
                            RecBuffer.Add(new PointF(P2.X + Buffer * (float)Math.Cos(slope - 0.25 * PI), P2.Y + Buffer * (float)Math.Sin(slope - 0.25 * PI)));
                            RecBuffer.Add(new PointF(P1.X + Buffer * (float)Math.Cos(slope - 0.75 * PI), P1.Y + Buffer * (float)Math.Sin(slope - 0.75 * PI)));
                            if (Controller.IfPointInPolygon(RecBuffer, new PointF(e.X, e.Y)))
                            {
                                Point temp = Transformer.ToScreen(new PointF((P1.X + P2.X) / 2, (P1.Y + P2.Y) / 2));
                                cursorp = new Point(temp.X + 195, temp.Y + 125);
                            }
                        }
                    }
                }
            }
            return cursorp;
        }

        //实现方法有待考虑
        public bool Union()
        {
            CLine templn = new CLine();
            int id = Line_Set[Controller.Selected[0]].GetID();
            templn.newCline(id, Line_Set[Controller.Selected[0]].LegendID);
            for (int i = 0; i < Controller.Selected.Count(); i++)
            {
                for (int j = 0; j < Line_Set[Controller.Selected[i]].Lines.Count(); j++)
                {
                    templn.Lines.Add(Line_Set[Controller.Selected[i]].Lines[j]);
                }
            }
            templn.updateMBR();
            DeleteLine();
            Line_Set.Add(templn);
            Controller.Selected = new List<int>();
            Controller.Selected.Add(Line_Set.Count() - 1);
            return true;
        }

        public bool unUnion()
         {
             try
             {
                 for (int i = 0; i < Line_Set[Controller.Selected[0]].Lines.Count(); i++)
                 {
                     CLine temp = new CLine();
                     //完善生成ID的步骤、重新生成外包矩形等操作，调用一些函数。。。
                     temp.newCline(IDGenerator.LineID(), Line_Set[Controller.Selected[0]].LegendID);
                     temp.Lines.Add(Line_Set[Controller.Selected[0]].Lines[i]);
                     temp.updateMBR();
                     Line_Set.Add(temp);
                 }
                 Line_Set.RemoveAt(Controller.Selected[0]);
                 Controller.Selected = new List<int>();
                 Controller.Selected.Add(Line_Set.Count() - 1);
                 return true;
             }
             catch
             {
                 return false;
             }
         }

        public bool Split()
        {
            try
            {
                return true;
            }
            catch
            {
                return false;
            }
        }

        //public Bitmap bmp_new = new Bitmap(Controller.View_Width, Controller.View_Height);

        public Bitmap drawlinelayer()
        {
            lnlayer = new Bitmap(Controller.View_Width, Controller.View_Height);
            Graphics a = Graphics.FromImage(lnlayer);
            for (int i = 0; i < Line_Set.Count(); i++)                              //重绘已存储的边
            {
                if (Line_Set[i].Lines != null)
                {
                    CLineLegend cll = (CLineLegend)Controller.MapLegends[Line_Set[i].LegendID];
                    Line_Set[i].linepen = new Pen(cll.color, cll.line_weight);
                    if (cll.Line_Style == CLineLegend.LineStyle.solidline)
                        Line_Set[i].linepen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
                    else if (cll.Line_Style == CLineLegend.LineStyle.dashline)
                    {
                        float[] dashValues = { 3, 3 };
                        Line_Set[i].linepen.DashPattern = dashValues;
                    }
                    for (int j = 0; j < Line_Set[i].Lines.Count(); j++)
                    {
                        int m;
                        Point screenp1 = new Point();
                        Point screenp2 = new Point();
                        for (m = 0; m + 1 < Line_Set[i].Lines[j].Count(); m++)
                        {
                            screenp1 = Transformer.ToScreen(Line_Set[i].Lines[j][m]);
                            screenp2 = Transformer.ToScreen(Line_Set[i].Lines[j][m + 1]);
                            a.DrawLine(Line_Set[i].linepen, screenp1, screenp2);
                            a.FillRectangle(Brushes.Blue, screenp1.X - 2, screenp1.Y - 2, 4, 4);
                        }
                        screenp1 = Transformer.ToScreen(Line_Set[i].Lines[j][m]);
                        a.FillRectangle(Brushes.Blue, screenp1.X - 2, screenp1.Y - 2, 4, 4);
                    }
                }
            }
            if (Controller.Selected != null)
            {
                Pen linepen=new Pen(Color.Transparent);
                for (int i = 0; i < Controller.Selected.Count(); i++)
                {
                    CLineLegend cll = (CLineLegend)Controller.MapLegends[Line_Set[Controller.Selected[i]].LegendID];
                    if(cll.color!=Color.SkyBlue)
                        linepen = new Pen(Color.SkyBlue, cll.line_weight);
                    else
                        linepen = new Pen(Color.Blue, cll.line_weight);
                    if (cll.Line_Style == CLineLegend.LineStyle.solidline)
                        linepen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
                    else if (cll.Line_Style == CLineLegend.LineStyle.dashline)
                    {
                        float[] dashValues = { 3, 3 };
                        linepen.DashPattern = dashValues;
                    }
                    for (int m = 0; m < Line_Set[Controller.Selected[i]].Lines.Count(); m++)
                    {
                        int j;
                        Point screenp1 = new Point();
                        Point screenp2 = new Point();
                        for (j = 0; j + 1 < Line_Set[Controller.Selected[i]].Lines[m].Count(); j++)
                        {
                            screenp1 = Transformer.ToScreen(Line_Set[Controller.Selected[i]].Lines[m][j]);
                            screenp2 = Transformer.ToScreen(Line_Set[Controller.Selected[i]].Lines[m][j + 1]);
                            a.DrawLine(linepen, screenp1, screenp2);
                            //a.FillRectangle(Brushes.Blue, screenp1.X - 2, screenp1.Y - 2, 4, 4);
                        }
                    }
                }
                if (Controller.Selected.Count() == 1 && Controller.selectsimple != null)
                {
                    for (int i = 0; i < Controller.selectsimple.Count(); i++)
                    {
                        Point screenp1 = new Point();
                        Point screenp2 = new Point();
                        for (int j = 0; j +1< Line_Set[Controller.Selected[0]].Lines[Controller.selectsimple[i]].Count(); j++)
                        {
                            screenp1 = Transformer.ToScreen(Line_Set[Controller.Selected[0]].Lines[Controller.selectsimple[i]][j]);
                            screenp2 = Transformer.ToScreen(Line_Set[Controller.Selected[0]].Lines[Controller.selectsimple[i]][j + 1]);
                            linepen.Color = Color.PaleGreen;
                            a.DrawLine(linepen, screenp1, screenp2);
                        }
                    }
                }
                if (Controller.current_Operation == Controller.OperationStyles.Editnode)
                {                 
                        Point screenp1 = new Point();
                        Point screenp2 = new Point();
                            for (int j = 0; j < Line_Set[Controller.Selected[0]].Lines.Count(); j++)
                            {
                                for (int m = 0; m < Line_Set[Controller.Selected[0]].Lines[j].Count(); m++)
                                {
                                    screenp1 = Transformer.ToScreen(Line_Set[Controller.Selected[0]].Lines[j][m]);
                                    a.FillRectangle(Brushes.Orange, screenp1.X - 4, screenp1.Y - 4, 8, 8);
                                }
                            }
                            if (Controller.selectnodeindex.X!=-1)
                            {
                                screenp1 = Transformer.ToScreen(Line_Set[Controller.Selected[0]].Lines[Controller.selectnodeindex.X][Controller.selectnodeindex.Y]);
                                a.FillRectangle(Brushes.Red, screenp1.X - 5, screenp1.Y - 5, 10, 10);
                            }
                            if (Controller.selectlineindex .X!=-1)
                            {
                                screenp1 = Transformer.ToScreen(Line_Set[Controller.Selected[0]].Lines[Controller.selectlineindex.X][Controller.selectlineindex.Y]);
                                screenp2 = Transformer.ToScreen(Line_Set[Controller.Selected[0]].Lines[Controller.selectlineindex.X][Controller.selectlineindex.Y + 1]);
                                linepen.Color = Color.Tomato;
                                a.DrawLine(linepen, screenp1, screenp2);
                            }
                    }
            }
            return lnlayer;
        }

        public Bitmap drawLine(Point startPoint, Point endPoint,int index)
        {
            lnlayer = new Bitmap(Controller.View_Width, Controller.View_Height);      
            lnlayer = drawlinelayer();
            Graphics a = Graphics.FromImage(lnlayer);   
            a.DrawLine(Line_Set[index].linepen, startPoint, endPoint);
            return lnlayer;
        }

       /* public Bitmap drawnode(int index)
       {
           Bitmap bmp_new = drawlinelayer();
            Graphics a = Graphics.FromImage(bmp_new);
           /*if (Line_Set[index].Lines[0].Count == 1)
           {
               bmp_new = drawlinelayer();
               a = Graphics.FromImage(bmp_new);
           }*/
           //else
           /*{
               Point screenp1 = new Point();
               screenp1 = Viewer.ToScreen(Line_Set[index].Lines[Line_Set[index].Lines.Count() - 1][Line_Set[index].Lines[Line_Set[index].Lines.Count() - 1].Count() - 1]);
               a.FillRectangle(Brushes.Blue, screenp1.X - 2, screenp1.Y - 2, 4, 4);
           }*/
          // return bmp_new;
       //}
        /*public Bitmap drawselectnode()
        {
            Graphics a = Graphics.FromImage(lnlayer);
            Point screenp1 = new Point();
            for (int i = 0; i < Controller.Selected.Count(); i++)
            {
                for (int j = 0; j < Line_Set[Controller.Selected[i]].Lines.Count(); j++)
                {
                    for (int m = 0; m < Line_Set[Controller.Selected[i]].Lines[j].Count(); m++)
                    {
                        screenp1 = Viewer.ToScreen(Line_Set[Controller.Selected[i]].Lines[j][m]);
                        a.FillRectangle(Brushes.Red, screenp1.X - 2, screenp1.Y - 2, 4, 4);
                    }
                }
            }
            return lnlayer;
        }*/
        public void SelectLine(PointF e)
        {
            float PI=(float)Math.PI;
            for (int i = 0; i < Line_Set.Count(); i++)
            {
                float trans;
                if (Controller.MyMap.Unit == "英寸")
                    trans = (float)1 / 96;
                else
                    trans = (float)2.54 / 96;
                float Buffer = Math.Max(((CLineLegend)Controller.MapLegends[Line_Set[i].LegendID]).line_weight * trans / 2, 10 * trans);
                if (Line_Set[i].MinBR.Lx - Buffer < e.X &&Line_Set[i].MinBR.Ly - Buffer < e.Y &&
                    Line_Set[i].MinBR.Rx + Buffer > e.X &&Line_Set[i].MinBR.Ry + Buffer > e.Y)
                {
                    for (int j = 0; j < Line_Set[i].Lines.Count(); j++)
                    {
                        for (int k = 0; k+1 < Line_Set[i].Lines[j].Count(); k++)
                        {
                            List<PointF> RecBuffer=new List<PointF> ();
                            PointF P1 = Line_Set[i].Lines[j][k];
                            PointF P2 = Line_Set[i].Lines[j][k+1];
                            float slope = (float)Math.Atan((P1.Y-P2.Y)/(P1.X-P2.X));
                            RecBuffer.Add(new PointF(P1.X + Buffer * (float)Math.Cos(slope - 0.75 * PI), P1.Y + Buffer * (float)Math.Sin(slope - 0.75 * PI)));
                            RecBuffer.Add(new PointF(P1.X + Buffer * (float)Math.Cos(slope + 0.75 * PI), P1.Y + Buffer * (float)Math.Sin(slope + 0.75 * PI)));
                            RecBuffer.Add(new PointF(P2.X + Buffer * (float)Math.Cos(slope + 0.25 * PI), P2.Y + Buffer * (float)Math.Sin(slope + 0.25 * PI)));
                            RecBuffer.Add(new PointF(P2.X + Buffer * (float)Math.Cos(slope - 0.25 * PI), P2.Y + Buffer * (float)Math.Sin(slope - 0.25 * PI)));
                            //RecBuffer.Add(new PointF(P1.X + Buffer * (float)Math.Cos(slope - 0.75 * PI), P1.Y + Buffer * (float)Math.Sin(slope - 0.75 * PI)));
                            if (Controller.IfPointInPolygon(RecBuffer,new PointF(e.X,e.Y)))
                            {
                                for (int m = 0; m < Controller.Selected.Count(); m++)
                                {
                                    if (i == Controller.Selected[m])
                                    {
                                        Line_Set[i].isselected = false;
                                        Controller.Selected.RemoveAt(m);
                                        return;
                                    }
                                }
                                Controller.SelectedObjectType = "Line";
                                Controller.Selected.Add(i);
                                Line_Set[i].isselected = true;
                                if (Line_Set[i].Lines.Count == 1 && Controller.Selected.Count==1)
                                    MainForm.pMainWin.Split.Enabled = true;
                                return;
                            }
                        }
                    }
                }
            }
        }
    }
}
